home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / src.zoo / src / port / blit.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-26  |  13.6 KB  |  518 lines

  1. /*                        Copyright (c) 1989 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*
  9.       $Header:
  10.     $Source:
  11. */
  12. static char    RCSid_[] = "$Source:";
  13.  
  14. /* bitblit code template generator for portable bitblt code (S. A. Uhler)
  15.  *
  16.  * This file contains templates used to generate fast, yet portable bit-blit
  17.  * code.  Currently only monochrome bitmaps are supported.  The templates
  18.  * are assembled with cpp, optionally in multiple passes to aid in debugging.
  19.  */
  20.  
  21. %include <stdio.h>
  22. %include "bitmap.h"
  23.  
  24. %define RIGHT        0x0    /* direction right -> left */
  25. %define DOWN        0x0    /* direction top->bottom */
  26. %define UP            0x10    /* direction bottom up */
  27. %define LEFT        0x20    /* direction right to left */
  28. %define SMALL        0x40    /* less than 1 full word */
  29. %define ALIGNED    0x80    /* src & dst aligned, no shifts */
  30. %define NSRC        1        /* no source required */
  31.  
  32. extern int bit_debug;
  33.  
  34. %define dprintf    if(bit_debug)fprintf
  35.  
  36. static char nsrc[16] = {        /* fold no source cases */
  37.     0,0,0,0,
  38.     0xf&~DST, 0xf&~DST, 0xf&~DST, 0xf&~DST,
  39.     0xf&DST, 0xf&DST, 0xf&DST, 0xf&DST, 
  40.     0xf, 0xf, 0xf, 0xf
  41.     };
  42.  
  43. static char zsrc[16] = {        /* no source req'd cases */
  44.     1,0,0,0,0,
  45.     1,0,0,0,0,
  46.     1,0,0,0,0,
  47.     1 };    
  48.  
  49. /* table of inverted bitblts (changes the sense of black and white) */
  50.  
  51. char op_invert[16] = {
  52.     15, 7, 11, 3, 13, 5, 9, 1, 14, 6, 10, 2, 12, 4, 8, 0
  53.     };
  54.  
  55. /* the 16 bit-blit functions */
  56.  
  57. 5define ZERO(d,s)    (0)
  58. 5define NOR(d,s)    (~((d)|(s)))
  59. 5define AND2(d,s)    ((d)&~(s))
  60. 5define NPROJ2(d,s)    (~(s))
  61. 5define AND1(d,s)    (~(d)&(s))
  62. 5define NPROJ1(d,s)    (~(d))
  63. 5define XOR(d,s)    ((d)^(s))
  64. 5define NAND(d,s)    (~((d)&(s)))
  65. 5define AND(d,s)    ((d)&(s))
  66. 5define NXOR(d,s)    (~((d)^(s)))
  67. 5define PROJ1(d,s)    ((d))
  68. 5define OR2(d,s)    ((d)|~(s))
  69. 5define PROJ2(d,s)    (s)
  70. 5define OR1(d,s)    (~(d)|(s))
  71. 5define OR(d,s)        ((d)|(s))
  72. 5define ONE(d,s)    (~0)
  73.  
  74. /* incr and decr macros (redefine when src and dst word size are different) */
  75.  
  76. 4define SINC(x)    x++
  77. 4define DINC(x)    x++
  78. 4define SDEC(x)    x--
  79. 4define DDEC(x)    x--
  80.  
  81. /* The templates go here.  I could combine right->left and left-> right
  82.    into a single template, but its probably not worth the bother.
  83.    The src & dst aligned cases are needed because 32 bit shifts are
  84.    undefined (and wrong on the 3100).
  85. */
  86.  
  87. /* single word bitblt */
  88.  
  89. 2define Rop_s(op) \
  90.    for (i=count; i>0; i--) {            \
  91.       osrc = src;  SINC(src);                    \
  92.       *dst = op(*dst,(GETMSB(*osrc,lshift) | GETLSB(*src,rshift))) \
  93.                     & lmask | (*dst & ~lmask);\
  94.       src += s_skip;  dst += d_skip;                \
  95.       }
  96.  
  97. /* single word bitblt (src and dst aligned) */
  98.  
  99. 2define Rop_sa(op) \
  100.    for (i=count; i>0; i--) {            \
  101.       *DINC(dst) = op(*dst,*SINC(src)) & lmask | (*dst & ~lmask);\
  102.       src += s_skip;  dst += d_skip;                \
  103.       }
  104.  
  105. /* multiword left to right bitblt (src and dst aligned) */
  106.  
  107. 2define Rop_incr_a(op) \
  108.    for (i=count; i>0; i--) {            \
  109.       *DINC(dst) = op(*dst,*SINC(src)) & lmask | (*dst & ~lmask);\
  110.       LOOP(words-2,*DINC(dst) = op(*dst,*SINC(src))); \
  111.       *DINC(dst) = op(*dst,*SINC(src)) & rmask | (*dst & ~rmask);\
  112.       src += s_skip;  dst += d_skip;                \
  113.       }
  114.  
  115. /* multiword right to left bitblt (source and dest aligned) */
  116.  
  117. 2define Rop_decr_a(op) \
  118.    for (i=count; i>0; i--) {            \
  119.       *DDEC(dst) = op(*dst,*SDEC(src)) & rmask | (*dst & ~rmask);\
  120.       LOOP(words-2,*DDEC(dst) = op(*dst,*SDEC(src))); \
  121.       *DDEC(dst) = op(*dst,*SDEC(src)) & lmask | (*dst & ~lmask);\
  122.       src += s_skip;  dst += d_skip;                \
  123.       }
  124.  
  125. /* multiword left to right bitblt */
  126.  
  127. 2define Rop_incr_m(op) \
  128.    for (i=count; i>0; i--) {            \
  129.       osrc = src;  SINC(src);                    \
  130.       *DINC(dst) = op(*dst,(GETMSB(*SINC(osrc),lshift) \
  131.                     | GETLSB(*SINC(src),rshift))) \
  132.                     & lmask | (*dst & ~lmask);\
  133.       LOOP(words-2,*DINC(dst) = \
  134.             op(*dst,GETMSB(*SINC(osrc),lshift) | GETLSB(*SINC(src),rshift)) \
  135.             ); \
  136.       *DINC(dst) = op(*dst,(GETMSB(*SINC(osrc),lshift) \
  137.                     | GETLSB(*SINC(src),rshift))) \
  138.                     & rmask | (*dst & ~rmask);\
  139.       src += s_skip;  dst += d_skip;                \
  140.       }
  141.  
  142. /* multiword right to left bitblt */
  143.  
  144. 2define Rop_decr_m(op) \
  145.    for (i=count; i>0; i--) {            \
  146.       osrc = src;  SDEC(osrc);                    \
  147.       *DDEC(dst) = op(*dst,(GETMSB(*SDEC(osrc),lshift) \
  148.                     | GETLSB(*SDEC(src),rshift))) \
  149.                     & rmask | (*dst & ~rmask);\
  150.       LOOP(words-2,*DDEC(dst) = \
  151.             op(*dst,GETMSB(*SDEC(osrc),lshift) | GETLSB(*SDEC(src),rshift)) \
  152.             ); \
  153.       *DDEC(dst) = op(*dst,(GETMSB(*SDEC(osrc),lshift) \
  154.                     | GETLSB(*SDEC(src),rshift))) \
  155.                     & lmask | (*dst & ~lmask);\
  156.       src += s_skip;  dst += d_skip;                \
  157.       }
  158.  
  159. #ifdef UNROLL
  160.  
  161. /* an unrolled loop (some compilers -i.e. DEC3100 can't unroll 16 at a time) */
  162.  
  163. 3define LOOP(n,s) {                    \
  164.     register int cnt;                    \
  165.     for (cnt=(n); cnt>=8; cnt-=8) {        \
  166.        s;s;s;s;s;s;s;s;            \
  167.        }                        \
  168.     switch (cnt) {                    \
  169.        case  7: s; case  6: s; case  5: s; case  4: s;    \
  170.        case  3: s; case  2: s; case  1: s;         \
  171.        }                        \
  172.     }
  173. #else
  174. 3define LOOP(n,s) {\
  175.     register int cnt;\
  176.     for (cnt=(n); cnt>0; cnt--) {\
  177.        s;\
  178.         } \
  179.     }
  180. #endif
  181.  
  182. /* do all 16 cases - eliminating never-used cases saves code space */
  183.  
  184. 1define SWITCH(op,func) \
  185.         switch(op&0xf) { \
  186.             case OPCODE(ZERO(DST,SRC)):    func(ZERO);        break; \
  187.             case OPCODE(NOR(DST,SRC)):        func(NOR);        break; \
  188.             case OPCODE(AND2(DST,SRC)):    func(AND2);        break; \
  189.             case OPCODE(NPROJ2(DST,SRC)):    func(NPROJ2);    break; \
  190.             case OPCODE(AND1(DST,SRC)):    func(AND1);        break; \
  191.             case OPCODE(NPROJ1(DST,SRC)):    func(NPROJ1);    break; \
  192.             case OPCODE(XOR(DST,SRC)):         func(XOR);        break; \
  193.             case OPCODE(NAND(DST,SRC)):    func(NAND);        break; \
  194.             case OPCODE(AND(DST,SRC)):        func(AND);        break; \
  195.             case OPCODE(NXOR(DST,SRC)):    func(NXOR);        break; \
  196.             case OPCODE(PROJ1(DST,SRC)):    func(PROJ1);    break; \
  197.             case OPCODE(OR2(DST,SRC)):        func(OR2);        break; \
  198.             case OPCODE(PROJ2(DST,SRC)):    func(PROJ2);    break; \
  199.             case OPCODE(OR1(DST,SRC)):         func(OR1);        break; \
  200.             case OPCODE(OR(DST,SRC)):        func(OR);        break; \
  201.             case OPCODE(ONE(DST,SRC)):        func(ONE);        break; \
  202.             }
  203.  
  204. 1define XWITCH(op,func)        /* use to turn off cases for debugging */
  205.  
  206. /* main entry point for memory-to-memory bit-blts */
  207.  
  208. mem_rop(dst_map,x_dst,y_dst,wide,high,op,src_map,x_src,y_src)
  209. BITMAP *dst_map;                /* source bitmap */
  210. BITMAP *src_map;                /* destination bitmap */
  211. int x_dst,y_dst;                /* destination coords */
  212. int x_src,y_src;                /* source coords */
  213. int wide,high;                    /* bitmap size */
  214. int op;                            /* bitmap function */
  215.    {
  216.     register DATA *dst;        /* dest bitmap base addresses */
  217.     register DATA *src;        /* source bitmap base addresses */
  218.     register DATA *osrc;        /* previous source addr */
  219.  
  220.     register int s_offset;            /* source bit offset */
  221.     register int d_skip;                /* words to next line in dst_map */
  222.     register int s_skip;                /* words to next line in src_map */
  223.     register int count=high;        /* # of rows */
  224.    register int words;                /* words across in inner loop (>32 bits) */
  225.    register DATA lmask;                /* bits on left to next long boundary */
  226.    register DATA rmask;                /* bits from last long on right */
  227.     register int lshift;                /* bits to shift left on next word */
  228.     register int rshift;                /* bits to shift right on previous word */
  229.     register int i;                    /* temporary and loop counter */
  230.  
  231.     /* clipping and argument checking */
  232.  
  233.     if (!src_map) {
  234.       if (bit_debug && op&0xf != 0xf&nsrc[op&0xf])
  235.            dprintf(stderr,"no src_map, setting op %d->%d\n",op&0xf,nsrc[op&0xf]);
  236.       op = 0xf&nsrc[op&0xf];                        /* a NULL src_map sources 1's */
  237.         }
  238.  
  239.     else if (zsrc[op&0xf])                     {
  240.       if (bit_debug && src_map)
  241.            dprintf(stderr,"op=%d, setting src_map->NULL\n",op&0xf);
  242.         src_map == BIT_NULL;                            /* don't check no src_map cases */
  243.         }
  244.  
  245. #ifdef INVERT
  246.     /* invert all raster ops */
  247.     op = op_invert[15&op];
  248. #endif
  249.  
  250.  
  251. %ifndef NOCLIP
  252.     
  253.     /* clip width and height */
  254.  
  255.     if (wide<0) {
  256.         dprintf(stderr,"Clip: w<0 (%d)\n",wide);
  257.         x_dst += wide;
  258.         wide = - wide;
  259.         }
  260.  
  261.     if (count<0) {
  262.         y_dst += count;
  263.         count = - count;
  264.         dprintf(stderr,"Clip: h<0 (%d)\n",count);
  265.         }
  266.  
  267.     /* clip destination */
  268.  
  269.    if (x_dst < 0) {
  270.         dprintf(stderr,"Clip: x_dst<0 (%d)\n",x_dst);
  271.         if (src_map)
  272.             x_src -= x_dst;
  273.         wide += x_dst;
  274.         x_dst = 0;
  275.         }
  276.  
  277.    if (y_dst < 0) {
  278.         dprintf(stderr,"Clip: y_dst<0 (%d)\n",y_dst);
  279.         if (src_map)
  280.             y_src -= y_dst;
  281.         count += y_dst;
  282.         y_dst = 0;
  283.         }
  284.  
  285.     /* clip source */
  286.  
  287.     if (src_map) {
  288.         if (x_src < 0) {
  289.             dprintf(stderr,"Clip: x_src<0 (%d)\n",x_src);
  290.             x_dst -= x_src;
  291.             wide += x_src;
  292.             x_src = 0;
  293.             }
  294.  
  295.         if (y_src < 0) {
  296.             dprintf(stderr,"Clip: y_src<0 (%d)\n",y_src);
  297.             y_dst-=y_src;
  298.             count+=y_src;
  299.             y_src=0;
  300.             }
  301.             
  302.         if ((i = x_src+wide - src_map->wide) > 0) {
  303.             dprintf(stderr,"Clip: wide too big for src (%d->%d)\n",wide,wide-i);
  304.             wide -= i;
  305.             }
  306.  
  307.         if ((i = y_src+count - src_map->high) > 0) {
  308.             dprintf(stderr,"Clip: high too big for src (%d->%d)\n",count,count-i);
  309.             count -= i;
  310.             }
  311.         }
  312.  
  313.     if ((i = x_dst + wide - dst_map->wide) > 0) {
  314.         dprintf(stderr,"Clip: wide too big for dst_map (%d->%d)\n",wide,wide-i);
  315.         wide -= i;
  316.         }
  317.     if ((i = y_dst + count - dst_map->high) > 0) {
  318.         dprintf(stderr,"Clip: high too big for dst_map (%d->%d)\n",count,count-i);
  319.         count -= i;
  320.         }
  321.  
  322.     if (wide<1 || count < 1) {
  323.         dprintf(stderr,"Clip: high or wide < 1 (%d,%d)\n",wide,count);
  324.         return(-1);
  325.         }
  326.  
  327.     /* end of clipping code */
  328.  
  329. %endif
  330.  
  331.     x_dst += dst_map->x0;
  332.     y_dst += dst_map->y0;
  333.     i=0;                            /* initialize bitblit direction */
  334.  
  335.     /* set initial conditions */
  336.  
  337.     if (DOFLIP && dst_map->primary->type&_FLIP) {
  338.         flip(dst_map->data,BIT_LINE(dst_map)*dst_map->primary->high);
  339.         dst_map->primary->type &= 3;
  340.         }
  341.  
  342.     words = ((x_dst+wide-1)>>LOGBITS) - (x_dst>>LOGBITS) + 1;
  343.     lmask = GETLSB((DATA) ~0, (x_dst&BITS));
  344.     rmask = GETMSB((DATA) ~0, (BITS - ((x_dst+wide-1)&BITS)));
  345.     dst = dst_map->data + BIT_LINE(dst_map)*y_dst + (x_dst>>LOGBITS);
  346.     d_skip = BIT_LINE(dst_map);        /* longs to next row */
  347.  
  348.    if (src_map) {
  349.  
  350.         /* convert source to internal form as needed */
  351.  
  352.         if (DOFLIP && src_map->primary->type&_FLIP) {
  353.             flip(src_map->data,BIT_LINE(src_map)*src_map->primary->high);
  354.             src_map->primary->type &= 3;
  355.             }
  356.  
  357.         x_src += src_map->x0;
  358.         y_src += src_map->y0;
  359.         src = src_map->data + BIT_LINE(src_map)*y_src + (x_src>>LOGBITS);
  360.         s_skip = BIT_LINE(src_map);
  361.  
  362.         /* compute source and dest bit offsets */
  363.  
  364.         lshift = (x_src&BITS) - (x_dst&BITS);
  365.         if (lshift > 0) {
  366.             rshift = (BITS+1) - lshift;
  367.             }
  368.         else  if (lshift < 0){
  369.             rshift = -lshift;
  370.             lshift = (BITS+1) - rshift;
  371.             src --;
  372.             }
  373.         else {
  374.             i |= ALIGNED;
  375.             }
  376.  
  377.         /* set blit direction (there are lots of ways to do this, pick 1) */
  378.  
  379.         if (src_map->data == dst_map->data) {
  380.             if (y_dst>y_src)
  381.                 i |= UP;
  382.             if (x_dst>x_src)
  383.                 i |= LEFT;
  384.             }
  385.  
  386.         }        /* end "if (source_map)" */
  387.  
  388.     if (words <=1 ) {
  389.         i |= SMALL;
  390.         lmask &= rmask;
  391.         }
  392.  
  393.     /* do the bitblt.  For each direction, adjust the initial condisions
  394.      * and choose the proper templates.  For machines where "x << (bits-in-x)"
  395.      * yields zero, the ALIGNED cases may be omitted
  396.      */
  397.  
  398. /*
  399.     dprintf(stderr,"DIR(%x) %dx%d %d,%d->%d,%d (0x%x->0x%x)\n",
  400.             i,count,wide,x_src,y_src,x_dst,y_dst,src,dst);
  401. */
  402.  
  403.    switch(i) {
  404.     case RIGHT|DOWN:                        /* top->bottom        left->right */
  405.         d_skip -= words;
  406.         s_skip -= (words + 1);
  407.         SWITCH(op,Rop_incr_m);
  408.       break;
  409.  
  410.     case RIGHT|DOWN|SMALL:                /* top->bottom        small */
  411.     case LEFT|DOWN|SMALL:
  412.         d_skip -= words - 1;
  413.         s_skip -= words;
  414.         SWITCH(op,Rop_s);
  415.       break;
  416.  
  417.     case RIGHT|DOWN|ALIGNED:            /* top->bottom        left->right */
  418.         d_skip -= words;
  419.         s_skip -= words;
  420.         SWITCH(op,Rop_incr_a);
  421.       break;
  422.  
  423.     case RIGHT|DOWN|SMALL|ALIGNED:    /* top->bottom        small */
  424.     case LEFT|DOWN|SMALL|ALIGNED:    
  425.         d_skip -= words;
  426.         s_skip -= words;
  427.         SWITCH(op,Rop_sa);
  428.       break;
  429.  
  430.     case RIGHT|UP:                            /* bottom->top        left->right */
  431.         dst += d_skip*(count-1);
  432.         d_skip = - (d_skip + words);
  433.         if (src_map) {
  434.             src += s_skip*(count-1);
  435.             s_skip = - (s_skip + words + 1);
  436.             }
  437.         SWITCH(op,Rop_incr_m);
  438.       break;
  439.  
  440.     case RIGHT|UP|SMALL:                    /* bottom->top        small */
  441.     case LEFT|UP|SMALL:                    /* bottom->top        small */
  442.         dst += d_skip*(count-1);
  443.         d_skip = - (d_skip + words - 1);
  444.         if (src_map) {
  445.             src += s_skip*(count-1);
  446.             s_skip = - (s_skip + words);
  447.             }
  448.         SWITCH(op,Rop_s);
  449.       break;
  450.  
  451.     case RIGHT|UP|ALIGNED:                /* bottom->top        left->right */
  452.         dst += d_skip*(count-1);
  453.         d_skip = - (d_skip + words);
  454.         if (src_map) {
  455.             src += s_skip*(count-1);
  456.             s_skip = - (s_skip + words);
  457.             }
  458.         SWITCH(op,Rop_incr_a);
  459.       break;
  460.  
  461.     case RIGHT|UP|SMALL|ALIGNED:        /* bottom->top        left->right */
  462.     case LEFT|UP|SMALL|ALIGNED:
  463.         dst += d_skip*(count-1);
  464.         d_skip = - (d_skip + words);
  465.         if (src_map) {
  466.             src += s_skip*(count-1);
  467.             s_skip = - (s_skip + words);
  468.             }
  469.         SWITCH(op,Rop_sa);
  470.       break;
  471.  
  472.     case LEFT|DOWN:                        /* top->bottom        right->left */
  473.         dst += words - 1;
  474.         d_skip += words;
  475.         if (src_map) {
  476.             src += words;
  477.             s_skip += words;
  478.             }
  479.         SWITCH(op,Rop_decr_m);
  480.       break;
  481.  
  482.     case LEFT|DOWN|ALIGNED:                /* top->bottom        right->left */
  483.         dst += words - 1;
  484.         d_skip += words;
  485.         if (src_map) {
  486.             src += words - 1;
  487.             s_skip += words;
  488.             }
  489.         SWITCH(op,Rop_decr_a);
  490.       break;
  491.  
  492.     case UP|LEFT:                            /* bottom->top        right->left */
  493.         dst += d_skip*(count-1) + words - 1;
  494.         d_skip = - (d_skip - words);
  495.         if (src_map) {
  496.             src += s_skip*(count-1) + words;
  497.             s_skip = -(s_skip - words);
  498.             }
  499.         SWITCH(op,Rop_decr_m);
  500.       break;
  501.  
  502.     case UP|LEFT|ALIGNED:                /* bottom->top        right->left */
  503.         dst += d_skip*(count-1) + words - 1;
  504.         d_skip = - (d_skip - words);
  505.         if (src_map) {
  506.             src += s_skip*count + words - 1;
  507.             s_skip = -(s_skip - words );
  508.             }
  509.         SWITCH(op,Rop_decr_a);
  510.       break;
  511.  
  512.     default:
  513.         dprintf(stderr,"Invalid direction: 0x%x\n",i);
  514.         break;
  515.         }
  516.     return(0);
  517.       }
  518.